package aos.ydksxt.core;

import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.hibernate.SessionFactory;
import org.hibernate.query.NativeQuery;
import org.hibernate.query.Query;
import org.hibernate.transform.Transformers;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 数据库DAO工具通用封装
 * Created by Stiofan on 2016/12/14.
 */
@Component
public class PersistenceDAO {
    @Resource
    private SessionFactory sessionFactory;

    public SessionFactory getSessionFactory() {
        return sessionFactory;
    }

    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    public List<Map<String, Object>> findAllBySql(String sqlString) {
        return findAllBySql(sqlString, null);
    }

    public List<Map<String, Object>> findAllBySql(String sqlString, Map<String, Object> parameters) {
        NativeQuery nativeQuery = getSessionFactory().getCurrentSession().createNativeQuery(sqlString);
        if (MapUtils.isNotEmpty(parameters)) {
            for (Map.Entry entry : parameters.entrySet()) {
                if (!"".equals(entry.getValue()) && entry.getValue() != null) {
                    nativeQuery.setParameter((String) entry.getKey(), entry.getValue());
                } else {
                    nativeQuery.setParameter((String) entry.getKey(), "null");
                }
            }
        }
        nativeQuery.setResultTransformer(Transformers.ALIAS_TO_ENTITY_MAP);//设置转换规则，将entiy转换为Map
        List results = nativeQuery.list();
        List<Map<String, Object>> returnResults = new ArrayList<>();
        if (ObjectUtils.anyNotNull(results)) {//针对查询结果进行处理，因ALIAS_TO_ENTITY_MAP结果集中字段为大写，后续将按照驼峰命名转换
            for (Object result : results) {
                Map<String, Object> resultMap = (Map<String, Object>) result;
                Map<String, Object> returnMap = new HashMap<>();
                for (Map.Entry<String, Object> entry : resultMap.entrySet()) {//开始将Map中的Key转换为驼峰命名形式
                    String[] keys = (entry.getKey()).split("_");
                    String humpKey = new String();
                    for (int i = 0; i < keys.length; i++) {
                        if (i == 0) {
                            humpKey += keys[i].toLowerCase();
                        } else {
                            humpKey += keys[i].substring(0, 1) + keys[i].substring(1).toLowerCase();
                        }
                    }
                    returnMap.put(humpKey, entry.getValue());
                }
                returnResults.add(returnMap);
            }
        }

        return returnResults;

    }

    public List findAllByHql(String hqlString) {
        return findAllByHql(hqlString, null);
    }

    public List findAllByHql(String hqlString, Map<String, Object> parameters) {
        Query query = getSessionFactory().getCurrentSession().createQuery(hqlString);
        if (MapUtils.isNotEmpty(parameters)) {
            for (Map.Entry<String, Object> entry : parameters.entrySet()) {
                query.setParameter(entry.getKey(), entry.getValue());
            }
        }
        return query.list();
    }

    public Object findSingleByHql(String hqlString, Map<String, Object> parameters) {
        Query query = getSessionFactory().getCurrentSession().createQuery(hqlString);
        if (MapUtils.isNotEmpty(parameters)) {
            for (Map.Entry<String, Object> entry : parameters.entrySet()) {
                query.setParameter(entry.getKey(), entry.getValue());
            }
        }
        List results = query.list();
        if (results.isEmpty()) {
            return null;
        } else {
            return results.get(0);
        }
    }

    public List findByHql(String hqlString, Class clazz) {
        Query query = getSessionFactory().getCurrentSession().createQuery(hqlString, clazz);
        return query.getResultList();
    }

    public void save(Object object) {
        getSessionFactory().getCurrentSession().save(object);
    }

    public void update(Object object) {
        getSessionFactory().getCurrentSession().update(object);
    }

    public void saveOrUpdate(Object object) {
        getSessionFactory().getCurrentSession().saveOrUpdate(object);
    }

    public int updateBySql(String updateSql) {
        return updateBySql(updateSql, null);
    }

    public int updateBySql(String updateSql, Map<String, Object> parameters) {
        NativeQuery query = getSessionFactory().getCurrentSession().createNativeQuery(updateSql);
        if (MapUtils.isNotEmpty(parameters)) {
            for (Map.Entry<String, Object> entry : parameters.entrySet()) {
                query.setParameter(entry.getKey(), entry.getValue());
            }
        }
        return query.executeUpdate();
    }

}
